Skip to content

chore: phase 1 cleanup — vendor deps, dev tooling, tests, CI#7

Open
llacoste wants to merge 4 commits into
masterfrom
chore/cleanup-phase-1
Open

chore: phase 1 cleanup — vendor deps, dev tooling, tests, CI#7
llacoste wants to merge 4 commits into
masterfrom
chore/cleanup-phase-1

Conversation

@llacoste

Copy link
Copy Markdown
Owner

Summary

Phase 1 of the threadscape cleanup. Foundational work — vendors the remaining CDN runtime deps, adds a dev-tooling baseline, pins the string-art algorithm's behavior with a snapshot test, and fixes a wave of implicit-global leaks the linter surfaced.

Nothing about the deployed artifact changes shape: still a static site, still served from repo root, still triggered by Digital Ocean's auto-pull on master. The runtime no longer makes any third-party CDN requests.

The first three commits each tell a self-contained story; the branch is best reviewed commit-by-commit:

  1. chore: vendor CDN deps and add dev tooling — gitignore, Node pin, Vitest/Playwright/ESLint/Prettier, vendored jspdf 2.5.1 + Font Awesome Free 6.7.2, VENDOR.md with SHA256s, unit tests for pure helpers, Playwright snapshot for the algorithm output.
  2. fix: scope implicit globals and apply Prettier formatting — adds let/const to 173 leaked loop counters and intermediate vars in string_art_generator.js and walkthrough.js. Snapshot test verifies byte-identical algorithm output. Prettier formatting bundled in.
  3. ci: add Verify-stage GitHub Actions workflow + Dependabot — single-stage matrix (Format / Lint / Unit / E2E), follows the convert_to_hex pattern. Dependabot tracks GH Actions + npm dev deps weekly; vendored libs are intentionally excluded (those refresh manually via VENDOR.md).

Test plan

  • npm run format:check — clean
  • npm run lint — 0 errors, 23 warnings (all dead-code surface area; Phase 5 input)
  • npm test — 14/14 unit tests pass
  • npm run test:e2e — 1/1 Playwright snapshot passes; line_sequence is byte-identical before and after the implicit-globals fix
  • Site loads + generator runs locally with vendored jspdf and Font Awesome (no CDN requests in the network panel)
  • CI workflow runs green on this PR

Risks

  • Algorithm regression — by far the biggest risk. Mitigated by the Playwright snapshot pinning line_sequence byte-for-byte. If the snapshot drifts in a future change, that's the signal to investigate before blessing.
  • CDN-vendor swapindex.html now loads Font Awesome and jspdf from assets/vendor/ instead of CDNs. Verified visually that all icons (fa-arrow-down, fa-rotate-left, fa-github-square, etc.) still render and that generatePDF still produces a downloadable PDF.
  • Deploy story — none. Digital Ocean still auto-pulls master; the dev-tooling files (package.json, node_modules, configs) are inert on the static host or gitignored.
  • Lock-in to npm dev tooling — accepted tradeoff per the conversation that produced this branch. Runtime stays vendored; if npm itself disappears one day, the site still works, only the dev workflow needs rebooting.

Phase 1 of N

The followup phases planned in the design conversation:

  • Phase 2 — write docs/algorithm.md explaining what string_art_generator.js actually does; rename single-letter vars (Rgrayscale_image, lline_index, etc.).
  • Phase 3 — replace numjs (777 KB) and opencv (8.6 MB) with plain Uint8Array/Float64Array + raw 2D canvas. Drops ~9.3 MB of vendored code.
  • Phase 4 — move the line-selection loop into a Web Worker; drop the setTimeout(0) chunking.
  • Phase 5 — delete dead code (startDrawing, pinsOutput references), fix the cropper-singleton TODO, wire up or hide the not_yet_implemented UI options, modularize.

llacoste added 4 commits June 12, 2026 11:46
Brings the site closer to "still works in 10 years with no network" by
removing the two remaining runtime CDN dependencies, and adds a standard
dev-tooling baseline (Vitest + Playwright + ESLint + Prettier) so future
cleanup can move safely.

- Vendored jspdf 2.5.1 and Font Awesome Free 6.7.2 (solid + brands) under
  assets/vendor/; index.html now loads them locally.
- VENDOR.md records source URL, version, and SHA256 for every vendored
  library so refreshes are reproducible.
- Vitest covers pure helpers (linspace, getSum, compareMul, compareAbsdiff,
  subtractArraysSimple, makeArr) via a small vm-based shim so source files
  can stay as <script>-tag globals for now (Phase 5 will modularize).
- Playwright pins the string-art algorithm's output: runs the generator
  against mandala_close.jpg with fixed parameters and snapshots the
  resulting line_sequence. This is the regression test for the algorithm
  itself ahead of Phase 3's planned numjs/opencv removal.
- ESLint config is permissive about the script-tag architecture (allows
  cross-file globals) but strict about no-undef — catches the kind of
  loop-counter leaks fixed in the follow-up commit.
- Pinned Node to 20.10.0 via .tool-versions (the only version installed
  via asdf locally).
- Removed assets/.DS_Store; .gitignore covers further leaks.
Loop counters and intermediate vars were being assigned without
let/var/const, leaking to window on every iteration. ESLint's no-undef
flagged 173 of them. The leaks were benign in practice — the leaked
names happened not to collide with anything — but they're a tripwire
for future edits, and at least one (the `weight` local in
NonBlockingLineCalculator) shadowed nothing only by accident.

The algorithm output is unchanged: the Playwright snapshot test
(test/e2e/algorithm_snapshot.spec.js) produces a byte-identical
line_sequence before and after this change.

Prettier formatting is bundled in because the lint clean-up touched
most of the same lines anyway.
Single-stage pipeline (Verify only). Digital Ocean handles deploy out
of band via auto-pull on master, so CI's only job is gating that push.

Verify fans into a matrix of four phases — Format, Lint, Unit, E2E —
matching the convert_to_hex pattern. E2E is the slow one (~12s plus
browser install), so the Playwright browser bundle is cached on
package-lock to keep cold runs reasonable.

Dependabot tracks github-actions and the npm dev tooling weekly. The
runtime libraries under assets/vendor/ are intentionally NOT tracked —
those refresh manually with checksum updates in VENDOR.md.
The CI run on Linux was failing because Playwright's default snapshot
path appends `-{projectName}-{platform}`, so a snapshot generated on
macOS as `mandala-close-100segments-chromium-darwin.json` wasn't found
when CI looked for `…-chromium-linux.json`.

Verified by generating the Linux snapshot inside the official
mcr.microsoft.com/playwright:v1.60.0-jammy container — the output was
byte-identical to the darwin one, confirming the algorithm is platform
invariant.

Stripped the suffix via snapshotPathTemplate so one fixture serves all
runners. If a future change ever introduces real platform divergence,
the test will fail loudly and we can re-add the suffix then.

Also aligned the test's `toMatchSnapshot` arg to the sanitized filename
Playwright actually writes (`_` → `-`), so the lookup and the fixture
on disk stay in sync.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant